/*--------------------------- MegaWave2 Module -----------------------------*/
/* mwcommand
  name = {eye_passLoc};
  version = {"1.0"};
  author = {"Baptiste Coulange"};
  function = {"Affiche le résultat d'un passe bande centré en l'endroit pointé"};
  usage = { 
  	 'z':[zoom=1.0]->zoom  "Zoom factor",	
     'o':[order=0]->order  "Zoom order: 0,1=linear,-3=cubic,3,5..11=spline",
	 in->in            "Fimage d'entrée",
	'h':[hautBand=0.04]->hautBand   "parametre du passe bande (cf PassBand)",
	'b':[basBand=0.07]->basBand     "parametre du passe bande (cf PassBand)",
	'a':[aBand=88.]->aBand    		"parametre du passe bande (cf PassBand)",	
	's'->s							"symétrisation de la selection (par rapport a la fréquence nulle)",
	'c'->c							"une partie de la fft centrale est conservée",
	'p'->p							"la comparaison se fait par produit scalaire",
	'O':oute<-oute					"recuperer l'image filtrée",
	'D'->D							"valeur absolue pour la zone de Fourier Locale",
	'C'->C							"carré pour la zone de Fourier Locale",
	'F':oute2<-oute2					"recuperer la zone active de Fourier",
 notused->window       "Window to view the image (internal use)"
          };
*/
/*----------------------------------------------------------------------

----------------------------------------------------------------------*/


#include <stdio.h>
#include "mw.h"
#include <math.h>
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)>(y)?(y):(x))
#define MMIN(x,y,a,b) MIN(MIN(x,y),MIN(a,b))
#define MMAX(x,y,a,b) MAX(MAX(x,y),MAX(a,b))

/* Include the window since we use windows facility */
#include "window.h"

extern Cimage clocal_zoom();
extern Fimage flocal_zoom();
extern void fzoom();
extern eOrientations();
extern perdecomp();
extern fthre();
extern fft2d();
extern fft2dview();
extern fop();
extern passLoc();
extern f2cimage();
extern void splot();
extern void fline_extract();
extern perdecomp();
extern zonFourLoc();
extern iFreqAsg();
extern fft2dshiftP();
extern fMin();

static Wframe *PlotWindow=NULL;  


/* Param structure used to send parameters to fview_notify() */

typedef struct passLoc_SParam {
Fimage imageRe;
  Fimage debut;
  Fimage fftInR;
  Fimage fftInI;
	Fimage filtr;	
  Fimage image_work;	
  Fimage zonFour;	
  double *hautBand,*basBand,*aBand;	
  char *s,*c,*D,*C,*p;
	Fimage oute,oute2,oute3,pscal;
	Fimage affichee;
	
	
} *passLoc_Param;


int oldx1,oldy1,oldevent,cscale_shown;
float zfactor;

void passLoc_notify_help()

{
  printf("\n\t\tHelp on line\n");

  printf("\nMouse:\n");
  printf("\tLeft button: choose point to compare.\n");


  printf("\nKeyboard:\n");

	printf("\tr: Revenir à la fft (pour une nouvelle selection).\n");
	printf("\tf: affichage de la transformée de Fourier de l'image filtrée.\n");
	printf("\ts: affichage de l'image spatiale filtrée\n");
	printf("\td: affichage de l'iamge de départ.\n");
	printf("\tl: Affichage de la ligne courante.\n");
	printf("\tc: Affichage de la colone courante.\n");
	printf("\tz: affichage de la zone d'action de la fft locale.\n");
	printf("\ta: affichage de la zone d'action de la dépliée. \n");
	printf("\te: affichage du produit scalaire des deux visualisations précédentes");
	printf("\tQ: Quit.\n");
  printf("\tH: Help.\n");

}






/*     A notify function must return a value ....      */
/*       0 if there was no event catched               */
/*     > 0 if there was an event catched (but Destroy) */
/*      -1 if the event Destroy was catched (or 'Q')   */

int passLoc_notify(ImageWindow,param)

Wframe *ImageWindow;

void *param;          /* Users's parameters: don't forget the cast ! */

{
  int x1,y1,wz,event,button_mask,ret,c,bgx,bgy;
  char mess[80];
  float ng;
  passLoc_Param images;
  Cimage image;
  Fimage filtr,finR,finI;
  char flag;
int x0=0;
  int y0=0;
	
	  /* For section */
  Fsignal section;
  int sx=500;
  int sy=200;
  char cflag=1;
  int norefresh=1;
	 /* Allocate section signal */


  if ((section = mw_change_fsignal(NULL,(image->ncol < image->nrow)?image->nrow:image->ncol)) == NULL)
      mwerror(FATAL,1,"Not enough memory\n");

  images = (passLoc_Param) param;  /* Cast */	
  filtr=images->filtr;
	
	
  image = mw_change_cimage(NULL,filtr->nrow,filtr->ncol);
  
	
  finR=mw_change_fimage(NULL,image->nrow,image->ncol);
  finI=mw_change_fimage(NULL,image->nrow,image->ncol);
	
  event = WUserEvent(ImageWindow); /* User's event on ImageWindow */	
  if (event < 0) ret=1; else ret=event;
	
  if (event != W_DESTROY)
     {
       WGetStateMouse(ImageWindow,&x1,&y1,&button_mask);	
	 }


					   
  switch(event)
    {
	 case W_MS_LEFT:
		if((x1>=0)&&(x1<image->ncol)&&(y1>=0)&&(y1<image->nrow)){
			
		if((image->ncol)%2==0){
			  x1 = x1-(image->ncol)/2+1;
			  } else {
			  x1 =x1-((image->ncol)-1)/2;  
		}
		if((image->nrow)%2==0){
			  y1 = y1-(image->nrow)/2+1;
			  } else {
			  y1 =y1-((image->nrow)-1)/2;  
		}
		  passLoc(images->hautBand,images->basBand,images->aBand,image->ncol,image->nrow,filtr,x1,y1,images->s,images->c);
		  
			
		  fop(filtr,finR,images->fftInR,NULL,NULL,NULL,&flag,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);	
  		  fop(filtr,finI,images->fftInI,NULL,NULL,NULL,&flag,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
		   fop(finR,filtr,finI,NULL,NULL,NULL,NULL,NULL,NULL,&flag,NULL,NULL,NULL,NULL,NULL);
 		fft2dshift(images->filtr,images->filtr);
		  fft2d(finR,finI,finR,finI,&flag);	
		  if(images->oute) {mw_copy_fimage(finR,images->oute);if(!(images->oute2))ret=-1;}
			mw_copy_fimage(finR,images->image_work);
		  mw_copy_fimage(finR,images->affichee);
			f2cimage(finR,image);
		
			/* Draw the images */

	
		  WLoadBitMapImage(ImageWindow,image->gray,image->ncol,image->nrow); 
  		  WRestoreImageWindow(ImageWindow,0,0,image->ncol,image->nrow); 
  		  WFlushWindow(ImageWindow);

	
			
		}			
		

	  	break;
	case  W_KEYPRESS:
	 c = WGetKeyboard();
      switch(c)
	{
	  case 'h': case 'H': passLoc_notify_help();
	  	break;	
	  case 'q':
		ret=-1;
			break;
			
		break;	
				
			
	  case 'f':

			  f2cimage(filtr,image);
			  mw_copy_fimage(filtr,images->affichee);
		      WLoadBitMapImage(ImageWindow,image->gray,image->ncol,image->nrow); 
  			  WRestoreImageWindow(ImageWindow,0,0,image->ncol,image->nrow); 
  			  WFlushWindow(ImageWindow);
			break;
		case'r':
			 
			  f2cimage(images->debut,image);
			  mw_copy_fimage(images->debut,images->affichee);
			  WLoadBitMapImage(ImageWindow,image->gray,image->ncol,image->nrow); 
  			  WRestoreImageWindow(ImageWindow,0,0,image->ncol,image->nrow); 
  			  WFlushWindow(ImageWindow);
			break;
		case 's':
			  f2cimage(images->image_work,image);
			  mw_copy_fimage(images->image_work,images->affichee);
			  WLoadBitMapImage(ImageWindow,image->gray,image->ncol,image->nrow); 
  			  WRestoreImageWindow(ImageWindow,0,0,image->ncol,image->nrow); 
  			  WFlushWindow(ImageWindow);
		
			break;
		case 'd':
			f2cimage(images->imageRe,image);
				mw_copy_fimage(images->imageRe,images->affichee);
			  WLoadBitMapImage(ImageWindow,image->gray,image->ncol,image->nrow); 
  			  WRestoreImageWindow(ImageWindow,0,0,image->ncol,image->nrow); 
  			  WFlushWindow(ImageWindow);
		break;
		case 'l' :
	     /* Draw an horizontal red line */
	      WSetTypePencil(W_COPY);
	      WSetSpecialColorPencil(ImageWindow);
	      if (WLoadBitMapImage(ImageWindow,image->gray,image->ncol,
				   image->nrow)!= 0) return(-1);
	      WRestoreImageWindow(ImageWindow,0,0,image->ncol,image->nrow); 
	      WDrawLine(ImageWindow,0,y1,image->ncol-1,y1);  
	      WFlushWindow(ImageWindow);	  
	      cscale_shown = 0;
	      
	      /* Compute and plot section */
	      if (PlotWindow != NULL) {x0=PlotWindow->x;y0=PlotWindow->y;}
	      else 
			{
		  x0 = ImageWindow->x + 2 ;
		  y0 = ImageWindow->x + 2 ;
		  if (y0 < 0) y0 = 0;
			}
	      fline_extract((char *) NULL, images->affichee, section, y1);
	      sprintf(section->name,"Plot a section");
	      PlotWindow = (Wframe *)
		  mw_get_window(PlotWindow,sx,sy,x0,y0,"");
	      splot(section,&x0,&y0,&sx,&sy,
		  &norefresh,(char *)PlotWindow,NULL,NULL);

	      /* Restore image without red line */
	      WRestoreImageWindow(ImageWindow,0,0,image->ncol,image->nrow); 
	      WFlushWindow(ImageWindow);
	    	
	  	  break;
	    
		case 'c' :
	  		
	      /* Draw a vertical red line */
	      WSetTypePencil(W_COPY);
	      WSetSpecialColorPencil(ImageWindow);
	      if (WLoadBitMapImage(ImageWindow,image->gray,image->ncol,
				   image->nrow)!= 0) return(-1);
	      WRestoreImageWindow(ImageWindow,0,0,image->ncol,image->nrow); 
	      WDrawLine(ImageWindow,x1,0,x1,image->nrow-1);  
	      WFlushWindow(ImageWindow);	  
	      cscale_shown = 0;

	      /* Compute and plot section */
	      if (PlotWindow != NULL) {x0 = PlotWindow->x;y0 = PlotWindow->y;}
	      else 
		{
		  x0 = ImageWindow->x + 2;
		  y0 = ImageWindow->x + 2;
		  if (y0 < 0) y0 = 0;
		}
	      fline_extract(&cflag, images->affichee, section,x1);
	      sprintf(section->name,"Plot a section");
	      PlotWindow = (Wframe *)
		mw_get_window(PlotWindow,sx,sy,x0,y0,"");
	      splot(section,&x0,&y0,&sx,&sy,
		    &norefresh,(char *)PlotWindow,NULL,NULL);

	      /* Restore image without red line */
	      WRestoreImageWindow(ImageWindow,0,0,image->ncol,image->nrow); 
	      WFlushWindow(ImageWindow);
	    
	  break;	
			
	}
	}
mw_delete_fimage(finI);
	mw_delete_fimage(finR);
	mw_delete_cimage(image);
	mw_delete_fsignal(section);
  return(ret);
}





/* Main loop */

Fimage eye_passLoc(in,zoom,window,order,hautBand,basBand,aBand,s,c,oute,oute2,C,D,p)
	Fimage in,oute,oute2;
    char   *window,*s,*c,*D,*C,*p;
	float *zoom;
	int *order;
	double *hautBand,*basBand,*aBand;
{
	int x0,y0;
	char flag;
	x0=50;
	y0=50;
    Wframe *ImageWindow;
    Fimage tmp,inCons;
	Cimage cimage;
	float inverse_zoom;
	inCons=mw_change_fimage(NULL,in->nrow,in->ncol);
	inverse_zoom=1;
	tmp = mw_new_fimage();
	tmp=mw_change_fimage(NULL,in->nrow,in->ncol);
	perdecomp(in,inCons,tmp);

  if (*zoom != 1.0) 
    {
      tmp = mw_change_fimage(NULL,0,0);

      if (tmp == NULL) mwerror(FATAL,1,"Not enough memory\n");
      if (*zoom>1.0) 
	fzoom(inCons,tmp,NULL,NULL,zoom,order,NULL,NULL);
      else {
	inverse_zoom = 1./(*zoom);
	fzoom(inCons,tmp,NULL,NULL,&inverse_zoom,order,NULL,(char *)1);
      }
      sprintf(tmp->name,"%s %.1fX",in->name,*zoom);
    }
  else {
	  tmp=mw_change_fimage(tmp,in->nrow,in->ncol);
      mw_copy_fimage(inCons,tmp);
  }
	perdecomp(tmp,tmp,NULL);
	passLoc_Param param;
	param = (passLoc_Param) malloc(sizeof(struct passLoc_SParam));
    if (param == NULL) mwerror(FATAL,1,"not enough memory\n");

	param->imageRe=mw_change_fimage(NULL,tmp->nrow,tmp->ncol);
	mw_copy_fimage(tmp,param->imageRe);
    fthre(tmp,tmp,NULL,(char *)1,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  	cimage=mw_change_cimage(NULL,tmp->nrow,tmp->ncol);

	param->fftInI=mw_change_fimage(NULL,tmp->nrow,tmp->ncol);
	param->fftInR=mw_change_fimage(NULL,tmp->nrow,tmp->ncol);
	
	fft2d(tmp,NULL,param->fftInR,param->fftInI,NULL);

	fop(param->fftInR,tmp,param->fftInI,NULL,NULL,NULL,NULL,NULL,NULL,&flag,NULL,NULL,NULL,NULL,NULL);



	fft2dshift(tmp,tmp);
	param->debut=mw_change_fimage(NULL,tmp->nrow,tmp->ncol);	
	mw_copy_fimage(tmp,param->debut);
	f2cimage(tmp,cimage);
	
	



	ImageWindow = (Wframe *)
    mw_get_window((Wframe *) window,cimage->ncol,cimage->nrow,x0,y0,cimage->name);
	
	
	if (ImageWindow == NULL)
    mwerror(INTERNAL,1,"NULL window returned by mw_get_window\n");
  	

	
	WLoadBitMapImage(ImageWindow,cimage->gray,cimage->ncol,cimage->nrow); 
  	WRestoreImageWindow(ImageWindow,0,0,cimage->ncol,cimage->nrow); 
  	WFlushWindow(ImageWindow);
	oldx1 = oldy1 = oldevent = -1;
    zfactor = *zoom;
	

	cscale_shown = 0;


	
	WSetUserEvent(ImageWindow,W_MS_BUTTON | W_KEYPRESS);

	param->D=D;
	param->C=C;
	param->c=c;
	param->s=s;	
	param->p=p;
	if (oute==NULL){param->oute=NULL;}
	else{
	param->oute=mw_change_fimage(oute,param->fftInR->nrow,param->fftInR->ncol);
	}
	if (oute2==NULL){param->oute2=NULL;}
	else{
	param->oute2=mw_change_fimage(oute2,param->fftInR->nrow,param->fftInR->ncol);
	}
	param->oute3=mw_change_fimage(NULL,param->fftInR->nrow,param->fftInR->ncol);
	param->pscal=mw_change_fimage(NULL,param->fftInR->nrow,param->fftInR->ncol);
	
	param->filtr=mw_change_fimage(NULL,param->fftInR->nrow,param->fftInR->ncol);
	param->image_work=mw_change_fimage(NULL,param->fftInR->nrow,param->fftInR->ncol);	
	param->affichee=mw_change_fimage(NULL,param->fftInR->nrow,param->fftInR->ncol);	
	param->hautBand=hautBand;
	param->basBand=basBand;
	param->aBand=aBand;
	param->zonFour=mw_change_fimage(NULL,param->fftInR->nrow,param->fftInR->ncol);

	mw_window_notify(ImageWindow,(void *)param,passLoc_notify);
  	mw_delete_fimage(tmp);
	mw_delete_fimage(inCons);
	mw_window_main_loop();

}
